package parser

import (
	"engine"
	regexp2 "github.com/dlclark/regexp2"
	"log"
	"path"
	"regexp"
	model "smarthome-model"
	"strings"
)

var (
	// ProdConfReg {{prodId}}_{{xxx}}.{{xxx}}
	ProdConfReg = regexp.MustCompile(`<a href="([0-9A-Z]{4}_[a-zA-Z]+\.[a-z]+)">([^<]*)</a>`)

	// ProdIconReg iconX.png
	ProdIconReg = regexp.MustCompile(`<a href="(icon[A-Z]\.png)">([^<]*)</a>`)

	// ResourceDir {{xxx}}/
	ResourceDir = regexp.MustCompile(`<a href="([0-9a-zA-Z_-]+/)">([^<]*)</a>`)

	// CustomFileReg {{xxx}}.{{xxx}}
	CustomFileReg = regexp2.MustCompile(`<a href="((?!icon).+[^_].\.[a-z]+)">([^<]*)</a>`, 0)
)

const (
	ProductConf        = "ProductConf"
	ProductIcon        = "ProductIcon"
	ProductResourceDir = "ProductResourceDir"
	ProductCustomFile  = "ProductCustomFile"
)

func ParseProductConfig(content []byte, url, prodId string) engine.ParserResult {
	prodConfigs := ProdConfReg.FindAllStringSubmatch(string(content), -1)
	prodIcons := ProdIconReg.FindAllStringSubmatch(string(content), -1)
	resourceDirs := ResourceDir.FindAllStringSubmatch(string(content), -1)
	customFiles := extractCustomFilesName(content, prodId, CustomFileReg)
	result := engine.ParserResult{}
	result = addResult(prodConfigs, ProductConf, url, prodId, result)
	result = addResult(prodIcons, ProductIcon, url, prodId, result)
	result = addResult(resourceDirs, ProductResourceDir, url, prodId, result)
	result = addResult(customFiles, ProductCustomFile, url, prodId, result)
	return result
}

func extractCustomFilesName(content []byte, prodId string, re *regexp2.Regexp) [][]string {
	var matches [][]string
	m, err := re.FindStringMatch(string(content))
	if err != nil {
		log.Printf("parse %s page failed\n", prodId)
		return matches
	}
	if m == nil {
		log.Printf("parse %s page failed\n", prodId)
		return matches
	}
	for m != nil {
		matches = appendSubMatch(matches, m)
		m, _ = re.FindNextMatch(m)
	}
	return matches
}

func appendSubMatch(submatches [][]string, m *regexp2.Match) [][]string {
	submatch := make([]string, 0)
	for _, group := range m.Groups() {
		submatch = append(submatch, group.String())
	}
	return append(submatches, submatch)
}

func addResult(resultSet [][]string, resultType, url, prodId string, pResult engine.ParserResult) engine.ParserResult {
	for _, results := range resultSet {
		result := results[1]
		item := model.ProdParseItem{
			Url:       url + result,
			ProdId:    prodId,
			ParseType: resultType,
		}
		switch resultType {
		case ProductConf, ProductIcon:
			item.FileType = strings.Replace(result, prodId, "prodId", -1)
			item.FilePath = path.Join(item.FileType, prodId, result)
			item.IsDir = false
		case ProductResourceDir:
			result = strings.Replace(result, prodId, "prodId", -1)
			item.FileType = strings.Replace(result, "/", "", -1)
			item.FilePath = path.Join(item.FileType, prodId, result)
			request := engine.Request{
				CurURL: url + result,
				RefURL: url,
				ParserFunc: func(c []byte) engine.ParserResult {
					return ParseResource(c, url+result, prodId, item.FilePath)
				},
			}
			pResult.Requests = append(pResult.Requests, request)
			item.IsDir = true
		case ProductCustomFile:
			item.FileType = strings.Replace(result, prodId, "prodId", -1)
			item.FilePath = path.Join(item.FileType, prodId, result)
			item.IsDir = false
		default:
			log.Println("addResult: unknown result type!")
			continue
		}
		pResult.Items = append(pResult.Items, item)

	}
	return pResult
}
